package cn.wen.yaling.xo.service.impl;

import cn.wen.yaling.commons.constant.RedisConstants;
import cn.wen.yaling.commons.entity.TypeEntity;
import cn.wen.yaling.commons.enums.ResourceStatus;
import cn.wen.yaling.commons.enums.SubjectStatus;
import cn.wen.yaling.commons.service.RedisService;
import cn.wen.yaling.commons.utils.RedisUtils;
import cn.wen.yaling.commons.vo.*;
import cn.wen.yaling.xo.dao.TypeDao;
import cn.wen.yaling.xo.service.ArticleService;
import com.fasterxml.jackson.databind.introspect.WithMember;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.wen.yaling.commons.utils.PageUtils;
import cn.wen.yaling.commons.utils.Query;

import cn.wen.yaling.xo.dao.SubjectDao;
import cn.wen.yaling.commons.entity.SubjectEntity;
import cn.wen.yaling.xo.service.SubjectService;
import org.springframework.transaction.annotation.Transactional;


@Slf4j
@Service("subjectService")
public class SubjectServiceImpl extends ServiceImpl<SubjectDao, SubjectEntity> implements SubjectService {

    @Autowired
    private TypeDao typeDao;

    @Autowired
    private SubjectDao subjectDao;

    @Autowired
    private RedisService redisService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private ArticleService articleService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SubjectEntity> page = this.page(
                new Query<SubjectEntity>().getPage(params),
                new QueryWrapper<SubjectEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<TypeEntity> getSubjectAllTypeBySubjectId(Integer subjectId) {
        // 通过类别的类型和优先级排序
        return typeDao.getSubjectAllTypeBySubjectId(subjectId);
    }

    @Override
    public List<SubjectVO> getAllArticleBySubjectId(Integer subjectId) {
        List<SubjectVO> subjects = new ArrayList<>();
        if (redisService.hasKey(RedisConstants.CACHE_SUBJECT_ARTICLE_LIST + ":" + subjectId)) {
            subjects = redisUtils.getListCache(RedisConstants.CACHE_SUBJECT_ARTICLE_LIST + ":" + subjectId, SubjectVO.class);
        } else {
            // 2、缓存不命中则到db中获取
            // 先获取当前专题下的全部模块  就是分类嘛
            List<TypeEntity> subjectTypes = getSubjectAllTypeBySubjectId(subjectId);
            // 通过分类来获取模块下的数据
            for (TypeEntity subjectType : subjectTypes) {
                SubjectVO subjectVO = new SubjectVO();
                subjectVO.setTypeName(subjectType.getTypeName());
                // 获取当前模块下的所有文章
                List<ArticleVO> articleVOS = articleService.getArticleListByTypeId(subjectType.getTypeId());
                subjectVO.setArticleList(articleVOS);
                subjects.add(subjectVO);
            }
            // 3、将db中的缓存获取到
            redisUtils.setListCache(RedisConstants.CACHE_SUBJECT_ARTICLE_LIST + ":" + subjectId, subjects);
        }
        return subjects;
    }

    @Override
    public List<SubjectListVO> getAllSubjectList() {
        List<SubjectListVO> subjects;
        // 1.判断缓存是否存在
        if (redisService.hasKey(RedisConstants.CACHE_ADMIN_SUBJECT_LIST)) {
            // 存在则获取缓存
            subjects = redisUtils.getListCache(RedisConstants.CACHE_ADMIN_SUBJECT_LIST, SubjectListVO.class);
        } else {
            // 2.如果不命中则需要数据库查询 获取的专题模块
            subjects = getSubjectListFromDB();
            // 存入到缓存中
            redisUtils.setListCache(RedisConstants.CACHE_ADMIN_SUBJECT_LIST, subjects, 60 * 60 * 24 * 10);
        }
        log.info("{}", subjects);
        // 返回
        return subjects;
    }

    @Override
    public boolean deleteByIds(Integer[] subjectIds) {
        // 修改状态
        boolean b = subjectDao.updateByIds(subjectIds, SubjectStatus.DELETED.getStatus());
        // 判断是否存在缓存
        if (redisService.hasKey(RedisConstants.CACHE_ADMIN_SUBJECT_LIST)) {
            redisService.del(RedisConstants.CACHE_ADMIN_SUBJECT_LIST);
        }
        redisService.del(RedisConstants.CACHE_BAR_LIST);
        return b;
    }

    @Transactional
    @Override
    public boolean addSubject(SubjectAddVO subjectAddVO) {
        // 删除信息需要删除指定的专题缓存 先添加在删除
        SubjectEntity target = new SubjectEntity();
        BeanUtils.copyProperties(subjectAddVO, target);
        target.setSubjectStatus(SubjectStatus.PUBLISHED.getStatus());
        target.setCreateTime(new Date());
        target.setUpdateTime(new Date());
        int res = subjectDao.insert(target);
        // 判断是否存在缓存
        if (redisService.hasKey(RedisConstants.CACHE_ADMIN_SUBJECT_LIST)) {
            redisService.del(RedisConstants.CACHE_ADMIN_SUBJECT_LIST);
        }
        redisService.del(RedisConstants.CACHE_BAR_LIST);
        return res > 0;
    }

    @Transactional
    @Override
    public boolean updateSubject(SubjectUpdateVO subjectUpdateVO) {
        SubjectEntity target = new SubjectEntity();
        BeanUtils.copyProperties(subjectUpdateVO, target);
        target.setUpdateTime(new Date());
        int i = subjectDao.updateById(target);
        // 判断缓存
        // 判断是否存在缓存
        if (redisService.hasKey(RedisConstants.CACHE_ADMIN_SUBJECT_LIST)) {
            redisService.del(RedisConstants.CACHE_ADMIN_SUBJECT_LIST);
        }
        redisService.del(RedisConstants.CACHE_BAR_LIST);
        return i > 0;
    }

    @Override
    public List<SubjectListVO> searchSubject(String subjectName) {
        QueryWrapper<SubjectEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("subject_status", SubjectStatus.DELETED.getStatus());
        queryWrapper.like("subject_name", subjectName);
        List<SubjectEntity> subjects = subjectDao.selectList(queryWrapper);
        return subjects.stream().map(item -> {
            SubjectListVO target = new SubjectListVO();
            BeanUtils.copyProperties(item, target);
            return target;
        }).collect(Collectors.toList());
    }

    @Override
    public List<SubjectAdminVO> getAllSimpleArticleInfoBySubjectId(Integer subjectId) {
        List<SubjectAdminVO> subjects = new ArrayList<>();
        if (redisService.hasKey(RedisConstants.CACHE_SUBJECT_ADMIN_ARTICLE_LIST + ":" + subjectId)) {
            subjects = redisUtils.getListCache(RedisConstants.CACHE_SUBJECT_ADMIN_ARTICLE_LIST + ":" + subjectId, SubjectAdminVO.class);
        } else {
            // 2、缓存不命中则到db中获取
            // 先获取当前专题下的全部模块  就是分类嘛
            List<TypeEntity> subjectTypes = getSubjectAllTypeBySubjectId(subjectId);
            // 通过分类来获取模块下的数据
            for (TypeEntity subjectType : subjectTypes) {
                SubjectAdminVO subjectAdminVO = new SubjectAdminVO();
                subjectAdminVO.setTypeName(subjectType.getTypeName());
                // 获取当前模块下的所有文章
                List<ArticleAdminVO> articleAdminVOS = articleService.getSimpleArticleListByTypeId(subjectType.getTypeId());
                subjectAdminVO.setArticleList(articleAdminVOS);
                subjects.add(subjectAdminVO);
            }
            // 3、将db中的缓存获取到
            redisUtils.setListCache(RedisConstants.CACHE_SUBJECT_ADMIN_ARTICLE_LIST + ":" + subjectId, subjects);
        }
        return subjects;
    }

    private List<SubjectListVO> getSubjectListFromDB() {
        QueryWrapper<SubjectEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("subject_status", SubjectStatus.DELETED.getStatus());
        List<SubjectEntity> subjects = subjectDao.selectList(queryWrapper);
        return subjects.stream().map(item -> {
            SubjectListVO target = new SubjectListVO();
            BeanUtils.copyProperties(item, target);
            return target;
        }).collect(Collectors.toList());
    }

}